#
#  RockStar.py
#  RockStar
#
#  This app is a StatusBar app that allows the user to set the rating for the current iTunes track
#  although this is the apps main function it also displays album art, song information and gives the user
#  access to basic play controls: back/playpause/next
#
#  Created by David Keegan on 6/4/08
#  Distributed under GNU General Public License v3
#  keegan3d@gmail.com
#  www.keegan3d.com
#  http://code.google.com/p/rockstarmenubar/
#

import os
import objc
from Foundation import *
from AppKit import *
from ScriptingBridge import *

import lib.osx.Applications

start_time = NSDate.date()

class RockStarAppDelegate(NSObject):
	currentTrack = None
	currentRataing = 0
	
	starImages = {}
	defaultAlbumArt = None
	iconBasePath = os.path.split(__file__)[0] + "/"
	
	iTunesID = "com.apple.iTunes"
	
	#IB plugs
	menu = objc.IBOutlet()
	
	ratingIndicator = objc.IBOutlet()
	
	trackInfoView = objc.IBOutlet()
	trackInfoMenuItem = objc.IBOutlet()
	
	trackNameLabel = objc.IBOutlet()
	artistAlbumLabel = objc.IBOutlet()
	trackArtworkImage = objc.IBOutlet()
	
	def applicationDidFinishLaunching_(self, notification):
		self.defaultAlbumArt = NSImage.alloc().initByReferencingFile_(self.iconBasePath + "default.png")
		starIcon = NSImage.alloc().initByReferencingFile_(self.iconBasePath + "star.png")
		
		# Load all the star icons
		for i in range(0, 101, 20):
			starIconStr = "star" + str(i)
			filePath = self.iconBasePath + starIconStr + ".png"
			self.starImages[starIconStr] = NSImage.alloc().initByReferencingFile_(filePath)
		
		statusbar = NSStatusBar.systemStatusBar()
		self.statusitem = statusbar.statusItemWithLength_(NSVariableStatusItemLength)
		self.statusitem.setImage_(self.starImages["star0"])
		self.statusitem.setHighlightMode_(1)
		
		#put the views in the menu
		self.trackInfoMenuItem.setView_(self.trackInfoView)
		
		#set settings for the indeicator
		self.ratingIndicator.cell().setImage_(starIcon)
		
		self.statusitem.setMenu_(self.menu)
		
		#Get the timer going
		self.timer = NSTimer.alloc().initWithFireDate_interval_target_selector_userInfo_repeats_(start_time, 5.0, self, "iTunesSync:", None, True)
		NSRunLoop.currentRunLoop().addTimer_forMode_(self.timer, NSDefaultRunLoopMode)

	#play control functions
	@objc.IBAction
	def next_(self, notification):
		iTunes = self.get_iTunesObject()
		if iTunes:
			try:
				iTunes.nextTrack()
			
			except Exception:
				pass
		
		self.updateSongInfo()
	
	@objc.IBAction
	def back_(self, notification):
		iTunes = self.get_iTunesObject()
		if iTunes:
			try:
				iTunes.previousTrack()
			
			except Exception:
				pass
			
		self.updateSongInfo()

	@objc.IBAction
	def playPause_(self, notification):
		iTunes = self.get_iTunesObject()
		if iTunes:
			try:
				iTunes.playpause()
				
			except Exception:
				pass
			
		self.updateSongInfo()
		
	@objc.IBAction
	def ratingAction_(self, notification):
		iTunes = self.get_iTunesObject()
		if iTunes:
			#get the rating level and convert it to 0-100 space
			newrating = self.ratingIndicator.intValue()
			newrating = newrating*20
			
			try:
				iTunes.currentTrack().setRating_(newrating)
				self.updateSongInfo()
				
			except Exception:
				pass

	def get_iTunesObject(self):
		#if iTunes is not running, do nothing
		if lib.osx.Applications.isAppRunning(self.iTunesID):
			try:
				iTunes = SBApplication.applicationWithBundleIdentifier_(self.iTunesID)
				return iTunes
				
			except Exception:
				#if we cant get an iTunes object set everything to the default
				self.setDefaultInfo()
				self.setDefaultImage()
				
		else:
			self.setDefaultInfo()
			self.setDefaultImage()

	#set the default track info
	def setDefaultInfo(self):
		self.trackNameLabel.cell().setTitle_("")
		self.artistAlbumLabel.cell().setTitle_("")
		
		self.statusitem.setImage_(self.starImages["star0"])
		self.ratingIndicator.setIntValue_(0)
		
		self.currentTrack = None
		self.currentRataing = 0
	
	#set the default album art
	def setDefaultImage(self):
		self.trackArtworkImage.setImage_(self.defaultAlbumArt)
	
	#update the song info in the menu
	#var update can force an update of the info even if the song has not changed
	def updateSongInfo(self, update=1):
		iTunes = self.get_iTunesObject()
		if iTunes:
			try:
				trackName = iTunes.currentTrack().name()
				if not(self.currentTrack == trackName) or update:
					trackArtist = iTunes.currentTrack().artist()
					trackAlbum = iTunes.currentTrack().album()
					trackRating = iTunes.currentTrack().rating()
			
					self.trackNameLabel.cell().setTitle_(trackName)
					self.artistAlbumLabel.cell().setTitle_("%s - %s" % (trackAlbum, trackArtist))
			
					self.statusitem.setImage_(self.starImages["star%s" % trackRating])
					self.ratingIndicator.setIntValue_(trackRating/20)
					
					self.currentTrack = trackName
					self.currentRataing = trackRating
			
			except Exception:
				self.setDefaultInfo()
			
			#try to set album art	
			try:
				artwork = iTunes.currentTrack().artworks()[0].data()
				self.trackArtworkImage.setImage_(artwork)

			except Exception:
				self.setDefaultImage()
			
	#function called by the timer, 
	#so it doesn't force an update of the info
	def iTunesSync_(self, notification):
		self.updateSongInfo(0)
